#!/bin/bash

# videoblerg.wordpress.com/2017/11/10/ffmpeg-and-how-to-use-it-wrong/comment-page-1/

# script dependencies
for cmd in mediainfo calc ffmpeg ffprobe; do
    which "$cmd" >/dev/null || exit 1
done

yesno() {
    answer=''
    prompt="$1 [yn]? "
    # superuser.com/questions/276531/clear-stdin-before-reading
    while read -r -t 0; do read -r; done
    until [[ "$answer" =~ ^[yn]$ ]]; do
        read -s -n1 -p "$prompt" answer
        [[ "$answer" != "" ]] && echo "$answer"
    done
    [[ "$answer" == n ]] && return 1
    return 0
}

file="$1"
vcodec=x264
pix_fmt=yuv420p

### CALCULATING VIDEO BITRATE ###
crf=21 # so he said: videoblerg.wordpress.com/2014/12/18/extreme-encoding-settings-quality-and-size/
ffmpeg -y -i "$file" -vcodec lib$vcodec -preset veryfast -pix_fmt "$pix_fmt" -profile:v baseline -an -crf $crf discard.mkv
# gives us bits per pixel (bpp), width and height, framerate
eval $(mediainfo --Output="Video;bpp=%Bits-(Pixel*Frame)%\nwidth=%Width%\nheight=%Height%\nframerate=%FrameRate%" discard.mkv)
rm discard.mkv
printf "bpp: $bpp\nwidth: $width\nheight: $height\nframerate: $framerate\n"
vbitrate="$(calc -p -- "${bpp}*${width}*${height}*${framerate}/1024")"
vbitrate="${vbitrate%.*}"
#################################
yesno "Calculated video bitrate: $vbitrate" || read -r -p "Enter video bitrate: " vbitrate
#~ vbitrate=1500
abitrate=128
preset=veryslow
# presets: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
tune=film
# tunes: film,animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency

bufsize=$((vbitrate+abitrate))
maxrate=$((vbitrate + vbitrate/3))

ffmpeg_cmd="ffmpeg -nostdin -hide_banner -analyzeduration 2147483647 -probesize 2147483647"
endopts="-max_muxing_queue_size 9999"

#~ -g 48 maximum keyframe interval? good for streaming, not needed in our use case.
#~ -x264opts no-scenecut see: video.stackexchange.com/a/24684 - despite additional (minimal) overhead, scenecut seems to be important

outfile="${file%.*}.$vcodec.$pix_fmt.v$vbitrate.a$abitrate.$preset.$tune.mp4"

case $vcodec in

x265)
echo ffmpeg -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -tune $tune -pass 1 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 -y /dev/null
$ffmpeg_cmd -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -tune $tune -pass 1 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" $endopts -f mp4 -y /dev/null

echo ffmpeg -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -tune $tune -pass 2 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 "${file%.*}.testy.$vbitrate.$preset.mkv"
$ffmpeg_cmd -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -tune $tune -pass 2 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" $endopts -f mp4 "$outfile"
;;

x264)
echo ffmpeg -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -profile:v high -tune $tune -pass 1 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 -y /dev/null
$ffmpeg_cmd -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -profile:v high -tune $tune -pass 1 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" $endopts -f mp4 -y /dev/null

echo ffmpeg -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -profile:v high -tune $tune -pass 2 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 "${file%.*}.testy.$vbitrate.$preset.mkv"
$ffmpeg_cmd -i "$file" -pix_fmt "$pix_fmt" -vsync 1 -vcodec lib$vcodec -b:v: ${vbitrate}k -bufsize ${bufsize}k -maxrate ${maxrate}k -preset $preset -profile:v high -tune $tune -pass 2 -acodec aac -b:a ${abitrate}k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" $endopts -f mp4 "$outfile"
;;
esac
